package com.itany.annotation;

import com.itany.exception.EmpCreateFailException;
import com.itany.util.ParameterUtil;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;

/**
 * Author:石小俊
 * Date: 2022/11/3 10:08
 */
public class EmpFactoryBean {

    private static Map<String,String> map;
    static {
        map = new HashMap<>();
        try {
            // 可以通过类加载器获取到对应资源的InputStream
            // Class.getClassLoader():获取指定类的类加载器
            // getResourceAsStream(name):获取指定资源文件的InpueStream
            // name:指定资源文件基于类加载路径根目录的地址
            // 即:资源文件相对于src目录的地址
            BufferedReader br = new BufferedReader(
                    new InputStreamReader(
                            EmpFactoryBean.class
                            .getClassLoader()
                            .getResourceAsStream("ioc.properties")));
            String line = null;
            // 按行读取文件中的每一行信息
            // 每一行的数据对应Map集合中的一组key-value
            while((line = br.readLine()) != null){
                // 考虑到文件中可能存在空行
                // 对于空行不进行读取,直接读取下一行
                if(!ParameterUtil.isNull(line)){
                    // 当不为空行时
                    // 每一行的数据格式为:key=value
                    // 通过等号分割,左边为key,右边为value
                    String[] arr = line.split("=");
                    String key = arr[0];
                    String value = arr[1];
                    map.put(key,value);
                }
            }
        } catch (Exception e) {
            // 静态初始化程序中发生意外异常的信号。
            // 抛出 ExceptionInInitializerError 表明在计算静态初始值或静态变量的初始值期间发生异常。
            // 即:在静态代码块中处理异常,必须通过ExceptionInInitializerError来处理
            e.printStackTrace();
            throw new ExceptionInInitializerError("加载资源文件出错");
        }
    }

    public static Emp getEmp(){
        try {
            // 通过反射创建Emp对象
            Class<Emp> c = Emp.class;
            // 通过反射调用对应对象的无参构造方法
            Emp emp = c.newInstance();
            // 获取Emp对象中的所有属性
            Field[] fields = c.getDeclaredFields();
            for(Field field : fields){
                // 对于Emp对象中的每一个属性,均通过@Value注解的value属性进行赋值
                // 获取对应属性的指定注解@Value
                Value valueAnntation = field.getAnnotation(Value.class);
                // 由于解析的资源文件存放的数据是一个key-value的格式
                // 先将对应文件中的资源获取出来
                // 将@Value注解的value属性值作为资源文件存放数据的key
                String key = valueAnntation.value();
                // 根据key去资源文件中查找对应的value
                String value = map.get(key);
                // 将对应的value注入给对应的属性
                // 由于所有属性均是通过private修饰的
                // 因此,需要破坏封装原则,取消权限控制检查
                field.setAccessible(true);
                // 为属性赋值
                field.set(emp,value);
            }
            return emp;
        } catch (Exception e) {
            e.printStackTrace();
            throw new EmpCreateFailException("Emp对象创建失败");
        }
    }
}
